package com.wedimob.slideshare.task;

import java.util.Observer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class PoolExecutor {

    private ThreadPoolExecutor executor;
    private Monitor monitor;
    private Results results = new Results();

    public Results getResults() {
        return results;
    }

    private static class MyRejectedExecutionHandelerImpl
            implements RejectedExecutionHandler
    {
        @Override
        public void rejectedExecution(Runnable runnable,
                ThreadPoolExecutor executor)
        {
            System.err.println(runnable.toString() + " : I've been rejected ! ");
        }
    }

    public PoolExecutor(int scaleFactor, Observer observer) {
        int cpus = Runtime.getRuntime().availableProcessors();
        int maxThreads = cpus * scaleFactor;
        maxThreads = (maxThreads > 0 ? maxThreads : 1);

        executor = new ThreadPoolExecutor(maxThreads, // core thread pool size
                maxThreads, // core thread pool size
                10, // time to wait before resizing pool
                TimeUnit.MILLISECONDS,
                new BlockingQueue<Runnable>(100 * maxThreads, 20),
                new MyRejectedExecutionHandelerImpl());
        monitor = new Monitor(executor);
        monitor.addObserver(observer);
        Thread tmonitor = new Thread(monitor);
        tmonitor.setDaemon(true);
        tmonitor.start();
    }

    public void execAsync(Task<?, ?> tasks) {
        // System.out.println("add Task " + tasks.getClass().toString());
        executor.execute(tasks);
    }

    public void waitEnd(long timeout, TimeUnit unit) throws ExecutionException {
        try {

            if (!executor.awaitTermination(timeout, unit)) {
                executor.shutdownNow();
            }
            if (!executor.awaitTermination(timeout, unit)) {
            }
        } catch (InterruptedException ex) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
            throw new ExecutionException(ex);
        }
    }

    public boolean cancel() {
        executor.shutdownNow();
        Thread.currentThread().interrupt();
        return true;
    }

    public boolean isCancelled() {
        return executor.isShutdown();
    }

    public boolean isDone() {
        return executor.isTerminated();
    }

    public void shutdown() {
        executor.shutdown();
    }
}
